home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung CD 2 (Tewi)(1994).iso
/
gnu
/
djgpp
/
go32
/
stubedit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-17
|
9KB
|
412 lines
/* This is file STUBEDIT.C */
/*
** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include "gotypes.h"
#include "stubinfo.h"
word32 offset_of_info = 0;
word32 size_of_info = 0;
StubInfo stub_info = {
STUB_INFO_MAGIC
};
char *key = stub_info.magic;
void find_info(char *filename)
{
FILE *f;
int ch, found = 0;
int key_p;
long key_max, key_cnt=0;
unsigned char header[6];
unsigned char test_magic[16];
f = fopen(filename, "rb");
if (f == 0)
{
char buf[100];
sprintf(buf, "Fatal error in stubedit reading %s", filename);
perror(buf);
exit(1);
}
fread(header, 6, 1, f);
key_max = header[4] + header[5]*256 + 1;
key_max *= 512;
/* First, look for tag */
fseek(f, -4L, 2);
fread(test_magic, 4, 1, f);
offset_of_info = (test_magic[0])
| (test_magic[1] << 8)
| (test_magic[2] << 16)
| (test_magic[3] << 24);
if (offset_of_info > 0 && offset_of_info < key_max)
{
fseek(f, offset_of_info, 0);
fread(test_magic, 16, 1, f);
if (strcmp((char *)test_magic, key) == 0)
found = 1;
}
if (!found)
{
fseek(f, 0L, 0);
key_p = 0;
while ((ch = fgetc(f)) != EOF)
{
if (ch == key[key_p])
{
key_p++;
if (key[key_p] == 0)
{
fgetc(f); /* the NULL */
offset_of_info = ftell(f) - 16; /* skip the NULL in the file */
found = 1;
break;
}
}
else
key_p = 0;
key_cnt++;
if (key_cnt > key_max)
break;
}
}
if (!found)
{
fprintf(stderr, "Error: I cannot find the stub info structure. Must be either\n");
fprintf(stderr, "this is not a stub'd program, or it is older and does not have one.\n");
exit(1);
}
fseek(f, offset_of_info + 16L, 0);
fread(&size_of_info, 1, 4, f);
stub_info.struct_length = size_of_info;
if (size_of_info > sizeof(StubInfo))
size_of_info = sizeof(StubInfo);
fseek(f, offset_of_info, 0);
fread(&stub_info, 1, (int)size_of_info, f);
fclose(f);
return;
}
void store_info(char *filename)
{
FILE *f;
f = fopen(filename, "r+b");
if (f == 0)
{
char buf[100];
sprintf(buf, "Fatal error in stubedit writing %s", filename);
perror(buf);
exit(1);
}
fseek(f, offset_of_info, 0);
fwrite(&stub_info, 1, (int)size_of_info, f);
fclose(f);
}
char *pose_question(char *question, char *default_answer)
{
static char response[200];
printf("%s ? [%s] ", question, default_answer);
fflush(stdout);
gets(response);
if (response[0] == '\0')
return 0;
return response;
}
typedef void (*PerFunc)(void *address_of_field, char *buffer);
void str_v2s(void *addr, char *buf)
{
if (*(char *)addr == 0)
strcpy(buf, "\"\"");
else
{
strncpy(buf, (char *)addr, 14);
buf[14] = 0;
}
}
void str_s2v(void *addr, char *buf)
{
if (strcmp(buf, "\"\"") == 0)
*(char *)addr = 0;
else
{
strncpy((char *)addr, buf, 14);
((char *)addr)[14] = 0;
}
}
void bool_v2s(void *addr, char *buf)
{
if (*(word8 *)addr)
strcpy(buf, "yes");
else
strcpy(buf, "no");
}
void bool_s2v(void *addr, char *buf)
{
switch (buf[0])
{
case 'y':
case 'Y':
case '1':
case 't':
case 'T':
*(char *)addr = 1;
break;
case 'n':
case 'N':
case '0':
case 'f':
case 'F':
*(char *)addr = 0;
break;
}
}
void ver_v2s(void *addr, char *buf)
{
char *field = (char *)(addr);
char *rtype = "unknown";
char *fmt = "%d.%d.%s%d";
switch (field[1])
{
case 'a':
rtype = "alpha";
break;
case 'b':
rtype = "beta";
break;
case 'f':
fmt = "%d.%d";
break;
case 'm':
rtype = "maint";
break;
}
sprintf(buf, fmt, field[3], field[2], rtype, field[0]);
}
void ver_s2v(void *addr, char *buf)
{
char *field = (char *)(addr);
int major = 0;
int minor = 0;
char rtype;
int release = 0;
char rstr[100];
rstr[0] = 'f';
sscanf(buf, "%d.%d.%[^0-9]%d", &major, &minor, &rstr, &release);
rtype = rstr[0];
field[3] = major;
field[2] = minor;
field[1] = rtype;
field[0] = release;
}
void num_v2s(void *addr, char *buf)
{
word32 v = *(word32 *)addr;
sprintf(buf, "%#lx (%dk)", v, v / 1024L);
}
void num_s2v(void *addr, char *buf)
{
word32 r = 0;
char s = 0;
sscanf(buf, "%i%c", &r, &s);
switch (s)
{
case 'k':
case 'K':
r *= 1024L;
break;
case 'm':
case 'M':
r *= 1048576L;
break;
}
*(word32 *)addr = r;
}
struct {
char *short_name;
char *long_name;
void *addr_of_field;
PerFunc val2string;
PerFunc string2val;
} per_field[] = {
{ "extender",
"Name of program to run as the extender (max 13 chars)",
stub_info.go32,
str_v2s, str_s2v
},
{ "version",
"Version of GO32 required to run this program",
stub_info.required_go32_version,
ver_v2s, ver_s2v
},
{
"minstack",
"Minimum amount of stack space (bytes/K/M)",
(void *)(&stub_info.min_stack),
num_v2s, num_s2v
},
{
"keepmem",
"Maximum amount of virtual memory to keep when spawning",
(void *)(&stub_info.max_keep_on_spawn),
num_v2s, num_s2v
},
{
"runfile",
"Base name of file to actually run (max 13 chars, \"\"=self)",
(void *)(&stub_info.actual_file_to_run),
str_v2s, str_s2v
},
{
"globbing",
"Enable command-line wildcard expansion (yes/no)",
(void *)(&stub_info.enable_globbing),
bool_v2s, bool_s2v,
},
{
"availmem",
"Amount of conventional memory to leave (bytes/K/M)",
(void *)(&stub_info.free_conventional_memory),
num_v2s, num_s2v
},
};
#define NUM_FIELDS (sizeof(per_field) / sizeof(per_field[0]))
#define HFORMAT "%-16s %s\n"
void give_help(void)
{
int i;
fprintf(stderr, "Usage: stubedit [-v] [-h] filename.exe [field=value . . . ]\n");
fprintf(stderr, "-h = give help -v = view info field=value means set w/o prompt\n");
fprintf(stderr, HFORMAT, "-field-", "-description-");
for (i=0; i < NUM_FIELDS; i++)
fprintf(stderr, HFORMAT, per_field[i].short_name, per_field[i].long_name);
exit(1);
}
main(int argc, char **argv)
{
int view_only = 0;
int i;
int need_to_save;
if (argc > 1 && strcmp(argv[1], "-h") == 0)
give_help();
if (argc > 1 && strcmp(argv[1], "-v") == 0)
{
view_only = 1;
argc--;
argv++;
}
if (argc < 2)
give_help();
find_info(argv[1]);
if (view_only)
{
char buf[100];
fprintf(stderr, HFORMAT, "-value-", "-field description-");
for (i=0; i<NUM_FIELDS; i++)
{
if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
{
per_field[i].val2string(per_field[i].addr_of_field, buf);
fprintf(stderr, HFORMAT, buf, per_field[i].long_name);
}
}
exit(0);
}
if (argc > 2)
{
int f, got, got_any = 0;
char fname[100], fval[100];
for (i=2; i < argc; i++)
{
fname[0] = 0;
fval[0] = 0;
sscanf(argv[i], "%[^=]=%s", fname, fval);
got = 0;
for (f=0; f<NUM_FIELDS; f++)
{
if (strcmp(per_field[f].short_name, fname) == 0)
{
got = 1;
got_any = 1;
if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
{
per_field[f].string2val(per_field[f].addr_of_field, fval);
}
else
fprintf(stderr, "Warning: This stub does not support field %s\n", fname);
}
}
if (!got)
{
fprintf(stderr, "Error: %s is not a valid field name.\n", fname);
give_help();
}
}
if (got_any)
store_info(argv[1]);
return 0;
}
need_to_save = 0;
for (i=0; i<NUM_FIELDS; i++)
{
char buf[100], *resp;
if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
{
per_field[i].val2string(per_field[i].addr_of_field, buf);
if ((resp = pose_question(per_field[i].long_name, buf)) != 0)
{
per_field[i].string2val(per_field[i].addr_of_field, resp);
need_to_save = 1;
}
}
}
if (need_to_save)
store_info(argv[1]);
return 0;
}